package com.baoxian.workschedule

import com.baoxian.cfg.SysCfg
import com.baoxian.workschedule.mapper.TaskWorkScheduleXmlLoader
import com.baoxian.workschedule.model.*
import com.baoxian.workschedule.util.CommonUtil
import com.baoxian.workschedule.util.ConstantsUtil
import org.apache.commons.lang.StringUtils
import org.apache.log4j.Logger

/**
 * User: ZhengCongChun
 * Date: 13-7-15
 * Time: 上午9:20
 * @Version 1.0
 *      To change this template use File | Settings | File Templates.
 */
@Singleton class TaskWorkSchedule {
    private static final Logger log = Logger.getLogger(TaskWorkSchedule.class)

    private static TaskWorkSchedule taskWorkSchedule = null

    private TaskWorkScheduleXmlLoader taskWorkScheduleXmlLoader

//    private static LinkedHashMap<String, Object> organizationConfig = null
//    private static GlobalWorkDayTimeModel globalWorkDayTimeConfig = null

    public static TaskWorkSchedule getInstance() {
        if (taskWorkSchedule == null || !taskWorkSchedule instanceof TaskWorkSchedule) {
            taskWorkSchedule = new TaskWorkSchedule()

        }
        return taskWorkSchedule
    }

    private TaskWorkSchedule() {
        try {
            log.debug("==== 初始化TaskWorkShcedule ====")
            taskWorkScheduleXmlLoader = new TaskWorkScheduleXmlLoader()
//            taskWorkScheduleXmlLoader.init("D:\\work\\projects\\workschedule\\trunk\\baoxian-task-work-schedule\\src\\main\\resources\\baoxian-task-workschedule.xml")
            taskWorkScheduleXmlLoader.init(SysCfg.get('task_workschedule_mapping_path'))
//            globalWorkDayTimeConfig = TaskWorkScheduleXmlLoader.globalWorkDayTimeConfig
//            organizationConfig = TaskWorkScheduleXmlLoader.organizationConfig

        } catch (Exception e) {
            log.error("==== Error: TaskWorkScheduleUtil初始化失败: ${e.getMessage()} ====", e)
        }
    }

    /**
     * 根据机构ID判断是否存在机构对应配置信息
     * @param orgId :机构ID
     * @return
     */
    boolean isExitsOraganization(String orgId) {
        boolean result = true
        if (!taskWorkScheduleXmlLoader?.organizationConfig?."${orgId}") {
            result = false
        }
        return result
    }

    /**
     * 判断任务是否可做
     * @param orgId 机构号
     * @param taskType 任务类型
     * @param executeDateTime 日期时间
     * @return 任务是否可做 and 第二提示语言
     */
    Map<String, Object> isCanProcessTask(String orgId, String taskType, String currentDateTime = (new Date().format(ConstantsUtil.DATE_TIME_FULL_FORMAT, TimeZone.getDefault())).toString()) {
        Map<String, Object> result = [:]

        //判断参数合法性
        if (StringUtils.isBlank(orgId) || StringUtils.isBlank(taskType)) {
            result.put(ConstantsUtil.TIP_MESSAGE, '非法参数错误：机构ID(orgId)和任务类型(taskType)不能为空')
            result.put(ConstantsUtil.EXITS_CONFIG, false)
            return result
        }

        if (!isExitsOraganization(orgId)) {
            result.put(ConstantsUtil.IS_CAN_PROCESS, true)
            result.put(ConstantsUtil.EXITS_CONFIG, false)
            return result
        }

        TaskModel taskModel = taskWorkScheduleXmlLoader?.organizationConfig?."${orgId}"?."${taskType}"
        //判断是否存在机构配置信息
        if (!taskModel) {
            result.put(ConstantsUtil.IS_CAN_PROCESS, true)
            result.put(ConstantsUtil.EXITS_CONFIG, false)
            return result
        } else {
            return canProcessTask(taskType, currentDateTime, taskModel)
        }
    }

    /**
     * 存在配置信息，判断是否可做任务
     * @param orgId
     * @param taskType
     * @param processDate
     * @return
     */
    private Map canProcessTask(String taskType, String processDate, TaskModel taskModel) {
        Map result = [:]
        result.put(ConstantsUtil.EXITS_CONFIG, true)

        String[] actionFlags = taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.actionFlags?.split(',')

        //1、是否在特定工作日中：
        boolean isSpeicalWorkDay = CommonUtil.isSpeicalWorkDay(taskModel?.workDayTime?.specialWorkDayTime, processDate)
        boolean isSpeicalWeekWorkDay = CommonUtil.isSpecialWeekWorkDay(taskModel?.workDayTime?.specialWeekWorkDay, processDate)

        //是否在机构特定工作日或特定星期工作日
        if (!isSpeicalWorkDay && !isSpeicalWeekWorkDay) {
            //既不在机构特定工作日，又不在特定星期工作日
            //a、是否在机构特定假日中，是特定假日则根据返回任务类型判断是否可做：支付、二支任务不可做；其他类型可做，附带提示信息
            //b、是否在全局假日中，在假日则根据返回任务类型判断是否可做：支付、二支任务不可做；其他类型可做，附带提示信息
            boolean isSpecialRestHoliday = CommonUtil.isSpecialRestHoliday(taskModel?.workDayTime?.specialHoliday, processDate)
            boolean isGlobalRestHoliday = CommonUtil.isGlobalRestHoliday(taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.holiday, processDate)

            //是否机构特定假日或全局假日
            if (isSpecialRestHoliday || isGlobalRestHoliday) {
                if (taskType == ConstantsUtil.TASK_TYPE_SECOND_PAYMENT || taskType == ConstantsUtil.TASK_TYPE_PAYMENT) {
                    result.put(ConstantsUtil.IS_CAN_PROCESS, false)
                    result.put(ConstantsUtil.ACTION_FLAG, taskModel?.actionFlag)
                    result.put(ConstantsUtil.FORBIDDEN_MESSAGE, taskModel?.tipMessage)

                    return result
                } else {
                    result.put(ConstantsUtil.IS_CAN_PROCESS, true)
                    result.put(ConstantsUtil.ACTION_FLAG, taskModel?.actionFlag)
                    result.put(ConstantsUtil.TIP_MESSAGE, taskModel?.tipMessage)

                    return result
                }
            } else {
                //既不在机构特定假日，又不在全局假日中
                BaseTimeModel workTime
                boolean isWeekWorkDay = CommonUtil.isSpecialWeekWorkDay(taskModel?.workDayTime?.weekWorkDay, processDate)

                //是否正常工作日
                if (isWeekWorkDay) {
                    workTime = new BaseTimeModel()
                    WeekWorkDayModel weekWorkDay = CommonUtil.isWeekDay(CommonUtil.dayForWeek(processDate), taskModel?.workDayTime?.weekWorkDay)
                    workTime.startTime = weekWorkDay?.startTime ?: taskModel?.workDayTime?.workTime?.endTime ?: taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.workTime?.startTime
                    workTime.endTime = weekWorkDay?.endTime ?: taskModel?.workDayTime?.workTime?.endTime ?: taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.workTime?.endTime
                } else {
                    //非正常工作日：如周六、周日
                    if (taskType == ConstantsUtil.TASK_TYPE_SECOND_PAYMENT || taskType == ConstantsUtil.TASK_TYPE_PAYMENT) {
                        result.put(ConstantsUtil.IS_CAN_PROCESS, false)
                        result.put(ConstantsUtil.ACTION_FLAG, actionFlags[1])
                        result.put(ConstantsUtil.FORBIDDEN_MESSAGE, taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.forbiddenMessage)

                        return result
                    } else {
                        result.put(ConstantsUtil.IS_CAN_PROCESS, true)
                        result.put(ConstantsUtil.ACTION_FLAG, actionFlags[0])
                        result.put(ConstantsUtil.FORBIDDEN_MESSAGE, taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.tipMessage)

                        return result
                    }
                }
                Map scheduleDateTime = CommonUtil.getCurrentWorkingHours(processDate, workTime)
                result.putAll(getProcessTimeOutResult(scheduleDateTime, taskType, processDate, taskModel))
                return result
            }
        } else {
            //在机构特定工作日或特定星期工作日
            //特定工作日:specialWorkDayTime
            CommonDayTimeModel specialWorkDayTime = CommonUtil.isWorkingDate(processDate, taskModel?.workDayTime?.specialWorkDayTime)
            //特定的星期工作日:speicalWeekWorkDay
            WeekWorkDayModel specialWeekWorkDay = CommonUtil.isWeekDay(CommonUtil.dayForWeek(processDate), taskModel?.workDayTime?.specialWeekWorkDay)

            String startTime = specialWorkDayTime?.startTime ?: specialWeekWorkDay?.startTime ?: taskModel?.workDayTime?.workTime?.startTime ?: taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.workTime?.startTime
            String endTime = specialWorkDayTime?.endTime ?: specialWeekWorkDay?.endTime ?: taskModel?.workDayTime?.workTime?.endTime ?: taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.workTime?.endTime

            BaseTimeModel workTime = new BaseTimeModel(startTime: startTime, endTime: endTime)
            Map scheduleDateTime = CommonUtil.getCurrentWorkingHours(processDate, workTime)

            result.putAll(getProcessTimeOutResult(scheduleDateTime, taskType, processDate, taskModel))

            if (result?.get(ConstantsUtil.IS_CAN_PROCESS) && (taskType == ConstantsUtil.TASK_TYPE_SECOND_PAYMENT || taskType == ConstantsUtil.TASK_TYPE_PAYMENT)) {
                result?.put(ConstantsUtil.ACTION_FLAG, actionFlags[0])
                result?.put(ConstantsUtil.FORBIDDEN_MESSAGE, taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.tipMessage)
            }

            return result
        }
    }

    /**
     * 获得是否处理超时结果
     * @param scheduleDateTime
     *      机构处理任务日期的运营时间
     * @param taskType
     *      任务类型
     * @param processDate
     *      处理日期
     * @param taskModel
     * @return Map
     *{'isCanProcess', 'actionFlag', 'tipMessage', 'exitsConfig'}
     */
    private Map getProcessTimeOutResult(Map scheduleDateTime, String taskType, String processDate, TaskModel taskModel) {
        Map result = [:]

        int preProcessTime = taskModel?.preProcessTime ?: taskWorkScheduleXmlLoader?.globalWorkDayTimeConfig?.preProcessTime
        boolean isTimeOut = CommonUtil.isProcessTimeOut(scheduleDateTime, preProcessTime, processDate)


        if (isTimeOut) {
            if (taskType == ConstantsUtil.TASK_TYPE_SECOND_PAYMENT || taskType == ConstantsUtil.TASK_TYPE_PAYMENT) {
                result.put(ConstantsUtil.IS_CAN_PROCESS, false)

            } else {
                result.put(ConstantsUtil.IS_CAN_PROCESS, true)
            }
        } else {
            result.put(ConstantsUtil.IS_CAN_PROCESS, true)
        }
        result.put(ConstantsUtil.ACTION_FLAG, taskModel?.actionFlag)
        result.put(ConstantsUtil.FORBIDDEN_MESSAGE, taskModel?.tipMessage)

        return result
    }

    /**
     * 重新加载XML内容，刷新内存数据
     * @return
     */
    boolean refeshConfigInfo() {
        return taskWorkScheduleXmlLoader?.refreshConfigInfo()
    }
}
